package com.yungam.imcs.controller.equip;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.google.common.collect.Lists;
import com.google.common.collect.Maps;
import com.yungam.common.bean.equip.Equipment;
import com.yungam.common.bean.equip.EquipmentConfig;
import com.yungam.common.bean.process.ProductionProcess;
import com.yungam.common.bean.product.ProductionProduct;
import com.yungam.common.response.RetDTO;
import com.yungam.common.service.EquipmentConfigService;
import com.yungam.common.service.EquipmentService;
import com.yungam.common.service.ProductionProcessService;
import com.yungam.common.service.ProductionProductService;
import com.yungam.other.bean.MesEquipment;
import com.yungam.other.bean.MesFrEquipment;
import com.yungam.other.db_service.MesEquipmentService;
import com.yungam.other.db_service.MesFrEquipmentService;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import io.swagger.annotations.ApiParam;
import org.apache.commons.lang.StringUtils;
import org.springframework.web.bind.annotation.*;

import javax.annotation.Resource;
import java.util.ArrayList;
import java.util.LinkedHashSet;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

@Api(tags = "设备管理页面接口")
@RestController
@RequestMapping("/equip")
public class EquipManageController {

    @Resource
    private EquipmentService equipmentService;
    @Resource
    private MesEquipmentService mesEquipmentService;
    @Resource
    private MesFrEquipmentService mesFrEquipmentService;
    @Resource
    private EquipmentConfigService equipmentConfigService;
    @Resource
    private ProductionProductService productionProductService;
    @Resource
    private ProductionProcessService productionProcessService;

    @ApiOperation("获取所有的设备信息")
    @GetMapping("/equips")
    public RetDTO<?> getEquipments() {
        QueryWrapper<Equipment> queryWrapper = new QueryWrapper<>();
        queryWrapper.select(Equipment.class, col -> !col.getProperty().equals("equImg"));
        return RetDTO.data(equipmentService.list(queryWrapper));
    }

    @ApiOperation("分页获取设备信息")
    @GetMapping("/equipsByPage")
    public RetDTO<?> getEquipmentsByPage(@ApiParam("设备名称") @RequestParam(required = false) String equipName,
                                         @ApiParam("页号") @RequestParam(required = true) int pageNum,
                                         @ApiParam("每页数量") @RequestParam(required = true) int pageSize) {
        QueryWrapper<Equipment> queryWrapper = new QueryWrapper<>();
        if (StringUtils.isNotBlank(equipName)) {
            queryWrapper.like("equ_name", equipName);
        }
        IPage<Equipment> page = new Page<>(pageNum, pageSize);
        return RetDTO.data(equipmentService.page(page, queryWrapper));
    }

    @ApiOperation("设备上传图片")
    @PostMapping("/img")
    public RetDTO<?> saveImg(@ApiParam("设备实体") @RequestBody Equipment equipment) {
        equipmentService.updateById(equipment);
        return RetDTO.success();
    }

    /* 从 mes 同步 iot 设备 */
    @ApiOperation("mes 同步 iot 设备")
    @GetMapping("/updateFromMes")
    public RetDTO<?> updateEquipsFromMes() {
        List<MesEquipment> mesList = mesEquipmentService.list();
        Map<String, MesEquipment> map = Maps.newHashMap();
        for (MesEquipment met : mesList) map.put(met.getEqptNo(), met);

        QueryWrapper<Equipment> queryWrapper = new QueryWrapper<>();
        queryWrapper.select(Equipment.class, col -> !col.getProperty().equals("equImg"));
        List<Equipment> list = equipmentService.list(queryWrapper);
        List<String> update = list.size() == 0 ? Lists.newArrayList() :
                list.stream().map(Equipment::getEquNumber).collect(Collectors.toList());

        // 找到需要更新的设备
        List<String> add = Lists.newArrayList();
        for (String s : map.keySet()) {
            if (update.contains(s)) continue;
            add.add(s);
        }

        for (String s : add) {
            MesEquipment met = map.get(s);
            Equipment equipment = new Equipment();
            equipment.setEquNumber(met.getEqptNo());
            equipment.setEquName(met.getEqptName());
            equipment.setEquState(0);
            equipmentService.save(equipment);
        }

        List<MesFrEquipment> mesFrList = mesFrEquipmentService.list();
        Map<String, MesFrEquipment> frMap = Maps.newHashMap();
        for (MesFrEquipment mf : mesFrList) frMap.put(mf.getEqptNo(), mf);

        List<Equipment> newList = equipmentService.list(queryWrapper);
        for (Equipment equipment : newList) {
            if (!frMap.containsKey(equipment.getEquNumber())) continue;
            equipment.setFrNo(frMap.get(equipment.getEquNumber()).getFrNo());
            equipment.setStationNo(frMap.get(equipment.getEquNumber()).getFrId());
            equipment.setStationName(frMap.get(equipment.getEquNumber()).getFrName());
            equipmentService.updateById(equipment);
        }

        return RetDTO.success();
    }

    @ApiOperation("获取设备的参数配置信息")
    @GetMapping("configData")
    public RetDTO<?> getConfigData(@ApiParam("设备 id") Integer equId) {
        List<EquipmentConfig> list = equipmentConfigService.list(new QueryWrapper<EquipmentConfig>()
                .eq("equ_id", equId));
        return RetDTO.data(list);
    }

    @ApiOperation("查询正在工作中的设备")
    @GetMapping("/equipsOfWork")
    public RetDTO<?> getEquipsOfWork() {
        List<ProductionProduct> list = productionProductService.list(new QueryWrapper<ProductionProduct>()
                .eq("state", 0).isNull("end_time").orderByAsc("production_id"));
        if (list.size() == 0) return RetDTO.data(null);

        List<String> productSnList = list.stream().map(ProductionProduct::getProductSn)
                .collect(Collectors.toList());
        List<ProductionProcess> processes = productionProcessService.list(new QueryWrapper<ProductionProcess>()
                .in("product_sn", productSnList)
                .eq("state", 0)
                .isNull("end_time")
                .orderByAsc("quality_id"));

        if (processes.size() == 0) return RetDTO.data(null);

        QueryWrapper<Equipment> queryWrapper = new QueryWrapper<>();
        queryWrapper.select(Equipment.class, col -> !col.getProperty().equals("equImg"));
        List<Equipment> equipmentList = equipmentService.list(queryWrapper);
        Map<String, Integer> map = Maps.newHashMap();
        for (Equipment equipment : equipmentList) {
            map.put(equipment.getEquNumber(), equipment.getEquId());
        }
        List<Integer> ans = Lists.newArrayList();
        for (ProductionProcess process : processes) {
            if (map.containsKey(process.getEquNo())) {
                ans.add(map.get(process.getEquNo()));
            }
        }
        // 去重
        ans = new ArrayList<>(new LinkedHashSet<>(ans));
        return RetDTO.data(ans);
    }

    /**
     * 根据 id 判断设备是否可能在作业中
     * 即罐号未完成 & 工序未完成
     */
    @ApiOperation("根据 id 判断设备是否可能在作业中")
    @GetMapping("/isWorking")
    public RetDTO<?> isEquipWorking(Integer id) {
        List<ProductionProduct> list = productionProductService.list(new QueryWrapper<ProductionProduct>()
                .eq("state", 0).isNull("end_time").orderByAsc("production_id"));
        if (list.size() == 0) return RetDTO.data(false);

        List<String> productSnList = list.stream().map(ProductionProduct::getProductSn)
                .collect(Collectors.toList());
        List<ProductionProcess> processes = productionProcessService.list(new QueryWrapper<ProductionProcess>()
                .in("product_sn", productSnList)
                .eq("state", 0)
                .isNull("end_time")
                .orderByAsc("quality_id"));

        if (processes.size() == 0) return RetDTO.data(false);
        List<String> equNos = processes.stream().map(ProductionProcess::getEquNo).collect(Collectors.toList());

        Equipment equipment = equipmentService.getById(id);
        boolean isWorking = equNos.contains(equipment.getEquNumber());
        return RetDTO.data(isWorking);
    }
}
